package com.springx.examples.showcase.service;

import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.springx.examples.showcase.entity.Admin;
import com.springx.examples.showcase.entity.Resource;
import com.springx.examples.showcase.entity.Role;
import com.springx.examples.showcase.repository.mybatis.AdminMapper;
import com.springx.examples.showcase.repository.mybatis.ResourceMapper;
import com.springx.examples.showcase.repository.mybatis.RoleMapper;
import com.springx.modules.utils.Collections3;
import com.springx.shiro.domain.Account;
import com.springx.shiro.domain.ShiroResource;
import com.springx.shiro.domain.ShiroRole;
import com.springx.shiro.service.ShiroAccountService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.*;

/**
 * Created by test on 2015/8/26.
 */
@Service
public class ShiroAccountServiceImpl implements ShiroAccountService {
    @Autowired
    private AdminMapper adminMapper;
    @Autowired
    private ResourceMapper resourceMapper;
    @Autowired
    private RoleMapper roleMapper;

    /**
     * 查询所有角色
     *
     * @return
     */
    public List<ShiroRole> findAllRole() {
        List<Role> roleList = roleMapper.select(null);
        return roleConverter(roleList);
    }

    /**
     * 查询用户角色
     *
     * @param loginName
     * @return
     */
    @Override
    public List<ShiroRole> findRoleListByLoginName(String loginName) {
        Map<String, Object> params = ImmutableMap.<String, Object>of("username", loginName);
        List<ShiroRole> shiroRoleList = roleMapper.findRoleListByLoginName(params);
        return shiroRoleList;
    }

    /**
     * 通过角色Id获取资源权限配置
     *
     * @param roleId
     * @return
     */
    public List<String> findPermissionListByRole(Long roleId) {
        Map<String, Object> params = ImmutableMap.<String, Object>of("roleId", roleId);
        List<String> permissionList = roleMapper.findPermissionListByRole(params);
        return permissionList;
    }

    @Override
    public List<String> findAllPermissionList() {
        return roleMapper.findAllPermissionList(null);
    }

    /**
     * 查询所有生效的资源
     *
     * @return
     */
    public List<ShiroResource> findAllResource() {
        Example example = new Example(Resource.class);
        example.createCriteria().andEqualTo("isEnabled", "1");
        List<Resource> resourceList = resourceMapper.selectByExample(example);
        return resourceConverter(resourceList);
    }

    /**
     * 登录完成后,显示用户菜单集合
     *
     * @param loginName
     * @return
     */
    @Override
    public Map<Long, List<ShiroResource>> findMenuListByLoginName(String loginName) {
        Map<Long, List<ShiroResource>> result = Maps.newHashMap();
        if (StringUtils.isNotBlank(loginName)) {
            List<ShiroResource> shiroResourceList;
            if (isSuperAdmin(loginName)) {
                shiroResourceList = resourceMapper.findAllMenuList(null);
            } else {
                Map<String, Object> params = ImmutableMap.<String, Object>of("username", loginName);
                shiroResourceList = resourceMapper.findMenuListByLoginName(params);

            }
            result = getMenuMap(shiroResourceList);
        }

        return result;
    }


    /**
     * 登录名查询账户
     *
     * @param loginName
     * @return
     */
    public Account findAccountByLoginName(String loginName) {
        Example example = new Example(Admin.class);
        example.createCriteria().andEqualTo("username", loginName);
        List<Admin> adminList = adminMapper.selectByExample(example);
        Admin admin = CollectionUtils.isNotEmpty(adminList) ? adminList.get(0) : null;
        return adminConverter(admin);
    }

    @Override
    public Boolean isSuperAdmin(String loginName) {
        List<ShiroRole> shiroRoleList = this.findRoleListByLoginName(loginName);
        Boolean result = false;
        if (CollectionUtils.isNotEmpty(shiroRoleList)) {
            for (ShiroRole role : shiroRoleList) {
                if (role.getIsSystem()) {
                    result = true;
                    break;
                }
            }
        }
        return result;
    }

    /**
     * resource 转变shiroResource
     *
     * @param resourceList
     * @return
     */
    private List<ShiroResource> resourceConverter(List<Resource> resourceList) {
        List<ShiroResource> shiroResourceList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(resourceList)) {
            ShiroResource shiroResource = null;
            for (Resource resource : resourceList) {
                shiroResource = new ShiroResource();
                shiroResource.setId(resource.getId());
                shiroResource.setIsEnabled(resource.getIsEnabled());
                shiroResource.setLevel(resource.getLevel());
                shiroResource.setName(resource.getName());
                shiroResource.setParentId(resource.getParentId());
                shiroResource.setPermissionType(resource.getPermissionType());
                shiroResource.setPermissionKey(resource.getPermissionKey());
                shiroResource.setPermissionValue(resource.getPermissionValue());
                shiroResource.setSort(resource.getSort());
                shiroResource.setType(resource.getType());
                shiroResource.setUrl(resource.getUrl());
                shiroResourceList.add(shiroResource);
            }
        }
        return shiroResourceList;
    }

    /**
     * 角色转换shiroRole
     *
     * @param roleList
     * @return
     */
    private List<ShiroRole> roleConverter(List<Role> roleList) {
        List<ShiroRole> shiroRoleList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(roleList)) {
            ShiroRole shiroRole = null;
            for (Role role : roleList) {
                shiroRole = new ShiroRole();
                shiroRole.setId(role.getId());
                shiroRole.setIsSystem(role.getIsSystem());
                shiroRole.setCode(role.getCode());
            }
        }
        return shiroRoleList;
    }

    /**
     * admin 转换Account
     *
     * @param admin
     * @return
     */
    private Account adminConverter(Admin admin) {
        if (null == admin) return null;
        Account account = new Account();
        account.setId(admin.getId());
        account.setIsEnabled(admin.getIsEnabled());
        account.setIsLocked(admin.getIsLocked());
        account.setLoginDate(admin.getLoginDate());
        account.setLoginFailureCount(admin.getLoginFailureCount());
        account.setLoginIp(admin.getLoginIp());
        account.setOpenId(admin.getOpenId());
        account.setPassword(admin.getPassword());
        account.setSalt(admin.getSalt());
        account.setUsername(admin.getUsername());
        account.setUnionId(null);
        return account;
    }

    /**
     * 菜单根据parentId转换
     *
     * @param shiroResourceList
     * @return
     */
    private Map<Long, List<ShiroResource>> getMenuMap(List<ShiroResource> shiroResourceList) {
        Map<Long, List<ShiroResource>> result = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(shiroResourceList)) {
            List<ShiroResource> shiroResourceResultList = null;
            for (ShiroResource shiroResource : shiroResourceList) {
                shiroResourceResultList = result.get(shiroResource.getParentId());
                if (CollectionUtils.isEmpty(shiroResourceResultList)) {
                    shiroResourceResultList = Lists.newArrayList();
                }
                shiroResourceResultList.add(shiroResource);
                result.put(shiroResource.getParentId(), shiroResourceResultList);
            }
        }
        return result;
    }

}
